home *** CD-ROM | disk | FTP | other *** search
- /* -*- C -*-
- * OPTICON.C
- *
- * (c)Copyright 1994 by Tobias Ferber, ukjg@rz.uni-karlsruhe.de
- *
- * This file is part of the IconTools distribution
- *
- * OptIcon is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 1 of the License,
- * or (at your option) any later version.
- *
- * OptIcon is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /* $VER: $Id: opticon.c,v 1.16 1995/08/06 20:39:35 tf Exp $ */
-
- #include "version.h"
- static char versiontag[] = "$VER: $Id: opticon.c,v 1.16 1995/08/06 20:39:35 tf Exp $";
-
- /* Compile w/ -DDEBUG to output more information at runtime */
-
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-
- #include <exec/types.h>
- #include <exec/memory.h>
-
- #include <dos/dos.h>
- #include <dos/rdargs.h>
-
- #include <intuition/intuition.h>
- #include <intuition/intuitionbase.h>
-
- #include <workbench/workbench.h>
- #include <workbench/startup.h>
- #include <workbench/icon.h>
-
- #include "memfn.h"
-
- #ifdef __GNUC__
- /* suggest parentheses around assignment used as truth value */
- #define if(assignment) if( (assignment) )
- #endif /* __GNUC__ */
-
- extern struct Library *OpenLibrary(STRPTR, ULONG);
- extern void CloseLibrary(struct Library *);
- extern void CopyMem(APTR, APTR, ULONG);
- extern void *AllocMem(ULONG, ULONG);
- extern void FreeMem(void *, ULONG);
- extern ULONG TypeOfMem(void *);
- extern struct RDArgs *ReadArgs(STRPTR, LONG *, struct RDArgs *);
- extern LONG IoErr(void);
- extern BOOL PrintFault(LONG, STRPTR);
- extern BPTR Lock(STRPTR, LONG);
- extern void UnLock(BPTR);
- extern void FreeArgs(struct RDArgs *);
- extern struct DiskObject *GetDiskObject(char *);
- extern BOOL PutDiskObject(char *, struct DiskObject *);
- extern void FreeDiskObject(struct DiskObject *);
-
- struct IconBase *IconBase;
-
- void display_version_information(void)
- {
- static char license[]=
- "OptIcon is free software; you can redistribute it and/or modify\n"
- "it under the terms of the GNU General Public License as published\n"
- "by the Free Software Foundation; either version 1 of the License,\n"
- "or (at your option) any later version.\n"
- "\n"
- "OptIcon is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with OptIcon; see the file COPYING. If not, write to the\n"
- "Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
- ;
-
- puts("\nOptIcon Version " VERSION " (compiled " __DATE__ ", " __TIME__ ")\n"
- "(c)Copyright 1994,95 by Tobias Ferber, ukjg@rz.uni-karlsruhe.de\n");
-
- puts(license);
- }
-
-
- struct Image *free_image(struct Image *i)
- {
- if(i)
- {
- long size= i->Depth * i->Height * ((i->Width + 15) / 16) * sizeof(UWORD);
-
- if(i->ImageData && size > 0)
- FreeMem( i->ImageData, size );
-
- FreeMem( i, sizeof(struct Image) );
- }
-
- return (struct Image *)0L;
- }
-
- /* command line options */
- #define OPT_NOEXPAND (1<<0)
- #define OPT_CRITICAL (1<<1)
- #define OPT_VERBOSE (1<<2)
- #define OPT_REMAPV37 (1<<3)
-
- struct Image *optimize_image(struct Image *i, WORD planes, int optimode)
- {
- UWORD p16= i->Height * ((i->Width + 15) / 16); /* #of words per plane */
- UWORD *idata= i->ImageData;
- WORD d, dmax, D, P;
- UBYTE pp= 0; /* plane pick */
- UBYTE p10= 0; /* plane on/off */
-
- struct Image *o= i; /* optimized image */
-
- /* prevent silly args from being harmful */
-
- if(!i)
- return i;
-
- if(planes > 8)
- planes= 8;
-
- if(optimode & OPT_VERBOSE)
- {
- printf("(depth=%d, pick=%d, onoff=%d)", i->Depth,
- i->PlanePick,
- i->PlaneOnOff);
- fflush(stdout);
- }
-
- /*
- PRESCAN: Examine dmax planes of i and compute
-
- D = the real depth (without trailing 0 planes)
- pp = the new PlanePick value
- p10 = the new PlaneOnOff value
- */
-
- dmax= (0 < planes && planes < i->Depth) ? planes : i->Depth;
-
- for(d= D= 0; d<dmax; d++)
- {
- /* check if we have some image data for plane d */
- if(i->PlanePick & (1<<d))
- {
- UWORD n, *p, v;
-
- /* scan the image data of plane d */
- for(n=0, p=idata, v=*p; n < p16; n++, p++)
- if(*p != v)
- break;
-
- if(n==p16 && v==0xFFFF) /* plane d is entirely 1 */
- p10 |= (1<<d); /* pp bit is already 0 */
-
- if( n!=p16 || (n==p16 && v!=0x0000 && v!=0xFFFF) )
- pp |= (1<<d);
-
- if( n!=p16 || (n==p16 && v!=0x0000) )
- D= d;
-
- idata= &idata[p16];
- }
- else if(i->PlaneOnOff & (1<<d))
- {
- p10 |= (1<<d);
- D=d;
- }
- }
-
- ++D;
-
- if( (optimode & OPT_VERBOSE) && (D != dmax || pp != i->PlanePick || p10 != i->PlaneOnOff) )
- {
- printf(" -> (%d,%d,%d)", D,pp,p10);
- fflush(stdout);
- }
-
- /* compute the #of planes in the output image */
- P= ( planes>D && !(optimode & OPT_NOEXPAND) ) ? planes : D;
-
- if(P != i->Depth || pp != i->PlanePick || p10 != i->PlaneOnOff)
- {
- UWORD p8= p16 * sizeof(UWORD);
- UWORD *odata;
- ULONG osize= P * p8;
-
- if( o= (struct Image *)AllocMem(sizeof(struct Image),MEMF_CLEAR) )
- {
- if( odata= (UWORD *)AllocMem(osize,TypeOfMem(i->ImageData)|MEMF_CLEAR) )
- {
- CopyMem( (APTR)i, (APTR)o, sizeof(struct Image) );
- o->ImageData= odata;
-
- idata= i->ImageData;
-
- for(d=0; d<D; d++)
- {
- if( pp & (1<<d) )
- {
- if(i->PlanePick & (1<<d))
- {
- CopyMem( (APTR)idata, (APTR)odata, p8 );
- idata= &idata[p16];
- odata= &odata[p16];
- }
- else /* !PlanePick bit (should not happen) */
- {
- memset( (char *)odata, (i->PlaneOnOff & (1<<d)) ? 0xFF : 0x00, p8 );
- odata= &odata[p16];
- }
- }
- else /* !pp bit */
- {
- if(i->PlanePick & (1<<d))
- idata= &idata[p16];
-
- if( !(optimode & OPT_CRITICAL) )
- {
- memset( (char *)odata, (p10 & (1<<d)) ? 0xFF : 0x00, p8 );
- odata= &odata[p16];
- pp |= (1<<d);
- p10 &= ~(1<<d);
- }
- }
- }
-
- if(D>=3 && D<P) /* no need to check OPT_NOEXPAND sice P is < D if set */
- {
- UWORD *p;
-
- if( p= (UWORD *)malloc(p8) )
- {
-
- if( (optimode & OPT_REMAPV37) && p10<=7 )
- {
- /*
- REMAP: Make colors 4-7 become the last 4 in the palette
-
- Algo: (1) OR together all planes > 2,
- (2) invert the result,
- (3) AND it with plane 2 and
- (4) OR the result with all planes > 2
-
- Note: There is no need to expand the image data if p10 &~ %111 != 0
- */
-
- /* move to plane 2 */
-
- idata= i->ImageData;
-
- for(d=0; d<2; d++)
- if(i->PlanePick & (1<<d))
- idata= &idata[p16];
-
- if(i->PlanePick & (1<<2))
- {
- memcpy((char *)p, (char *)idata, p8);
- idata= &idata[p16];
- }
- else memset( (char *)p, (p10 & (1L<<2)) ? 0xFF : 0x00, p8 );
-
- /* or planes 3..D, invert them, AND the result with plane 2 */
-
- for(d=3; d<D; d++)
- {
- if(i->PlanePick & (1<<d))
- {
- memandnot( (char *)p, (char *)idata, p8 );
- idata= &idata[p16];
- }
- /* else bit d of i->PlaneOnOff is 0 --> no-op */
- }
-
- /* move to plane 3 */
-
- odata= o->ImageData;
-
- for(d=0; d<3; d++)
- if(pp & (1<<d))
- odata= &odata[p16];
-
- for(d=3; d<P; d++)
- {
- if( d>=D || pp & (1<<d) )
- {
- memor( (char *)odata, (char *)p, p8 );
- odata= &odata[p16];
- pp |= (1<<d);
- }
- }
- }
-
- else /* !REMAPV37 */
- {
- /*
- EXPAND: Remap the last 4 colors of i to the last 4 colors of o
-
- Algo: (1) OR together all planes but the last
- (2) AND the result with the last plane
- (3) set the result in all new planes
-
- Note: if any plane of i but the last is entirely 1 then we can
- simply copy the last plane of i to all new planes in o
- */
-
- idata= i->ImageData;
-
- if( p10 &~ (1<<(D-1)) == 0)
- {
- memset( (char *)p, 0x00, p8 );
-
- for(d=0; d<D-1; d++)
- {
- if(i->PlanePick & (1<<d))
- {
- memor( (char *)p, (char *)idata, p8 );
- idata= &idata[p16];
- }
- }
- /* else plane d is entirely 0 */
-
- if( i->PlanePick & (1<<(D-1)) )
- memand( (char *)p, (char *)idata, p8 );
- /* else the last plane is entirely 1 */
- }
- else /* move to the last plane */
- {
- for(d=0; d<D-1; d++)
- if(i->PlanePick & (1<<d))
- idata= &idata[p16];
-
- if( i->PlanePick & (1<<(D-1)) )
- memcpy( (char *)p, (char *)idata, p8 );
- else
- memset( (char *)p, 0xFF, p8 );
- }
-
- /* move to plane D */
-
- odata= o->ImageData;
-
- for(d=0; d<D; d++)
- if(pp & (1<<d))
- odata= &odata[p16];
-
- for(d=D; d<P; d++)
- {
- memcpy( (char *)odata, (char *)p, p8 );
- odata= &odata[p16];
- pp |= (1<<d);
- }
-
- }
-
- free(p);
- }
- else /* !p --> panic! */
- {
- FreeMem(o->ImageData,osize);
- FreeMem(o,sizeof(struct Image));
- o= (struct Image *)0L;
- }
- }
-
- o->Depth= P;
- o->PlanePick= pp;
- o->PlaneOnOff= p10;
-
- }
- else /* !odata */
- {
- FreeMem(o,sizeof(struct Image));
- o= (struct Image *)0L;
- }
- }
- }
-
- if(optimode & OPT_VERBOSE)
- {
- if(o && o!=i)
- printf(" -> (%d,%d,%d)", o->Depth, o->PlanePick, o->PlaneOnOff);
- putchar('\n');
- }
-
- return o;
- }
-
- /**/
-
- static char *tackon(char *pname, char *fname)
- {
- char *buf= (char *)malloc(strlen(pname)+strlen(fname)+2);
-
- if(buf)
- {
- register char *s= buf; *s= '\0';
-
- if(pname)
- {
- register int n= 0;
-
- while( *pname )
- n++, *s++= *pname++;
-
- if( n>0 && buf[n-1]!=':' && buf[n-1]!='/' )
- *s++ = '/';
- }
-
- if(fname) while( *fname )
- *s++ = *fname++;
-
- *s= '\0';
- }
-
- return buf;
- }
-
- /* main, opticon(), and doall() share the following vars */
-
- static char *whoami;
- static LONG args[8] = { 0,0,0,0,0,0,0,0 };
- WORD numplanes= 0;
- int optiflags= 0;
-
- int opticon(char *fname)
- {
- int rc= RETURN_OK;
-
- /* We initially assume `fname' to be or to have an icon. */
-
- char *iname= (char *)strdup(fname);
-
- if(optiflags & OPT_VERBOSE)
- printf("opticon `%s'\n",fname);
-
- if(iname)
- {
- struct DiskObject *icon;
-
- if( (icon= GetDiskObject(iname)) == NULL )
- {
- size_t x= strlen(iname) - 5;
-
- if(x>0 && !stricmp(&(iname[x]),".info"))
- {
- iname[x]= '\0';
- icon= GetDiskObject(iname);
- }
- }
-
- if(icon)
- {
- struct Gadget *g= &icon->do_Gadget;
-
- struct Image *ogr, *osr;
- int modified= 0;
-
- ogr= osr= (struct Image *)0L;
-
- if(g->GadgetRender && (g->Flags & GFLG_GADGIMAGE))
- {
- struct Image *i= (struct Image *)g->GadgetRender;
-
- if(optiflags & OPT_VERBOSE)
- printf(" :normal "), fflush(stdout);
-
- if( ogr= optimize_image(i,numplanes,optiflags) )
- {
- if(ogr != i)
- {
- g->GadgetRender= (APTR)ogr;
- ++modified;
- }
- else ogr= (struct Image *)0L; /* don't free ogr */
-
- if(g->SelectRender && (g->Flags & GFLG_GADGHIMAGE))
- {
- i= (struct Image *)g->SelectRender;
-
- if(optiflags & OPT_VERBOSE)
- printf(" :selected "), fflush(stdout);
-
- if( osr= optimize_image(i,numplanes, optiflags) )
- {
- if(osr != i)
- {
- g->SelectRender= (APTR)osr;
- ++modified;
- }
- else osr= (struct Image *)0L; /* don't free osr */
- }
- else
- {
- fprintf(stderr,"%s: %s.info: not enough free memory to optimize the selected image\n",whoami,iname);
- rc= ERROR_NO_FREE_STORE;
- }
- }
- }
- else
- {
- fprintf(stderr,"%s: %s.info: not enough free memory to optimize the normal image\n",whoami,iname);
- rc= ERROR_NO_FREE_STORE;
- }
- }
-
- /* SMART/S */
-
- if( rc == RETURN_OK && args[6] && (icon->do_Type == WBDRAWER || icon->do_Type == WBGARBAGE) )
- {
- BPTR lock= Lock(iname,ACCESS_READ);
-
- if( BADDR(lock) )
- UnLock(lock);
-
- else
- {
- icon->do_Type = WBTOOL;
- ++modified;
- }
- }
-
- if( modified && rc == RETURN_OK )
- {
- if( !PutDiskObject(iname,icon) )
- PrintFault(rc= IoErr(), iname);
- }
-
- if(ogr) ogr= free_image(ogr);
- if(osr) osr= free_image(osr);
-
- FreeDiskObject(icon);
- }
- else /* !icon */
- {
- PrintFault(rc= IoErr(), iname);
- fprintf(stderr,"%s: GetDiskObject() failed for %s[.info]\n",whoami,iname);
-
- if(args[7])
- rc= RETURN_OK; /* keep running */
- }
-
- free(iname);
- }
- else /* !iname */
- {
- fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami);
- rc= ERROR_NO_FREE_STORE;
- }
-
- return rc;
- }
-
-
- int doall(char *pname)
- {
- int rc= RETURN_OK;
-
- struct FileInfoBlock *fib= (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL);
-
- if(optiflags & OPT_VERBOSE)
- printf("scanning `%s'\n",pname);
-
- if(fib)
- {
- /* set to 1 if we are to call opticon(pname) after UnLock() */
- int optme= 0;
-
- BPTR lock= Lock(pname, ACCESS_READ);
-
- if( BADDR(lock) )
- {
- if( Examine(lock,fib) )
- {
- /* not the initial call from main() for a file with ALL */
- if( (optme= (fib->fib_DirEntryType > 0) ? 0:1) == 0 )
- {
- while( (rc==RETURN_OK) && ExNext(lock,fib) && (IoErr() != ERROR_NO_MORE_ENTRIES) )
- {
- char *pcat= tackon(pname,fib->fib_FileName);
-
- if(pcat)
- {
- if(optiflags & OPT_VERBOSE)
- printf("found `%s'\n",pcat);
-
- if( fib->fib_DirEntryType > 0 ) /* directory */
- {
- rc= doall(pcat);
- }
-
- else /* file */
- {
- size_t x= strlen(pcat) - 5;
-
- if( stricmp(&pcat[x],".info") == 0 ) /* "*.info" file */
- {
- rc= opticon(pcat);
- }
- }
-
- free(pcat);
- }
- else /* !pcat */
- {
- fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami);
- rc= ERROR_NO_FREE_STORE;
- }
- }
- }
- }
- else PrintFault(rc= IoErr(), pname); /* Examine() failed */
-
- UnLock(lock);
- }
- else optme= 1; /* !lock */
- /*else PrintFault(rc= IoErr(), pname);*/
-
- if(optme && rc==RETURN_OK)
- rc= opticon(pname);
-
- FreeDosObject(DOS_FIB,fib);
- }
- else /* !fib */
- {
- fprintf(stderr,"%s: out of memory... aaaiiiiiieeeeeeeee!\n",whoami);
- rc= ERROR_NO_FREE_STORE;
- }
-
- return rc;
- }
-
-
- /**/
-
- int main(int argc, char **argv)
- {
- struct RDArgs *a;
- int rc= RETURN_OK;
-
- whoami= *argv;
-
- if( a= ReadArgs("FROM=NAME/A/M," /* 0 */
- "DEPTH=PLANES/N," /* 1 */
- "NOEXPAND/S," /* 2 */
- "CRITICAL/S," /* 3 */
- "REMAPV37/S," /* 4 */
- "VERBOSE/S," /* 5 */
- "SMART/S," /* 6 */
- "ALL/S", /* 7 */
- args, NULL) )
- {
- char **flist= (char **)args[0];
-
- if(args[1])
- {
- if( (numplanes= (WORD)*(LONG *)(args[1])) < 1 )
- {
- fprintf(stderr,"%s: Illegal maximum depth %d\n",whoami,numplanes);
- rc= RETURN_FAIL;
- }
- }
-
- if(flist && rc == RETURN_OK)
- {
- if( IconBase= (struct IconBase *)OpenLibrary(ICONNAME,36) )
- {
- if(args[2]) optiflags |= OPT_NOEXPAND;
- if(args[3]) optiflags |= OPT_CRITICAL;
- if(args[4]) optiflags |= OPT_REMAPV37;
- if(args[5]) optiflags |= OPT_VERBOSE;
-
- for(;*flist && rc == RETURN_OK;flist++)
- rc= args[7] ? doall(*flist) : opticon(*flist);
-
- CloseLibrary((struct Library *)IconBase);
- }
- else
- {
- fprintf(stderr,"%s: You need %s V36+",whoami,ICONNAME);
- rc= RETURN_ERROR;
- }
- }
- FreeArgs(a);
- }
- else /* !ReadArgs */
- {
- if(argc == 1)
- display_version_information();
- else
- PrintFault(rc= IoErr(),NULL);
- }
-
- return rc;
- }
-